home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 96 / maccd 96.iso / utilities / Mac OS X / DoubleCommand 1.3 / Source / MBHIDHack.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-19  |  14.4 KB  |  577 lines

  1. /*
  2.  * Name: MBHIDHack.cpp
  3.  * Project: DoubleCommand
  4.  * Author: Michael Baltaks <mbaltaks@mac.com>
  5.  * Creation Date: 2002-4-26
  6.  * Last Modified: 2002-7-19
  7.  * Originally based on iJect by Christian Starkjohann <cs@obdev.at> 
  8.  * Tabsize: 4
  9.  * Copyright: GNU General Public License version 2.0
  10.  */
  11.  
  12. //#define MB_DEBUG
  13.  
  14. #ifdef __cplusplus
  15.     extern "C"
  16.     {
  17. #endif
  18.  
  19. #include <mach/mach_types.h>
  20. #include <sys/systm.h>
  21.  
  22. extern int    MBHidInit(void);
  23. extern int    MBHidExit(void);
  24.  
  25. #ifdef __cplusplus
  26.     }
  27. #endif
  28.  
  29. #include "./MBHIDHack.h"
  30. #include <IOKit/system.h>
  31. #include <IOKit/assert.h>
  32. // this header for 10.1.5
  33. #include "./IOHIDSystem.h"
  34. //#include <IOKit/hidsystem/IOHIDSystem.h>
  35.  
  36. static void        *oldVtable = NULL;
  37. static void        *myVtable = NULL;
  38.  
  39. // int variable to set the configuration of DoubleCommand
  40. int dcConfig = 0;
  41.  
  42. class MBHIDHack : public IOHIDSystem
  43. {
  44. /* we must not declare anything which is not in our superclass
  45.  * since we want to pose as our superclass.
  46.  */
  47. public:
  48.   virtual void keyboardEvent(unsigned   eventType,
  49.       /* flags */            unsigned   flags,
  50.       /* keyCode */          unsigned   key,
  51.       /* charCode */         unsigned   charCode,
  52.       /* charSet */          unsigned   charSet,
  53.       /* originalCharCode */ unsigned   origCharCode,
  54.       /* originalCharSet */  unsigned   origCharSet,
  55.       /* keyboardType */     unsigned   keyboardType,
  56.       /* repeat */           bool       repeat,
  57.       /* atTime */           AbsoluteTime ts);
  58.   virtual void keyboardSpecialEvent(unsigned   eventType,
  59.                 /* flags */        unsigned   flags,
  60.                 /* keyCode  */     unsigned   key,
  61.                 /* specialty */    unsigned   flavor,
  62.                 /* guid */         UInt64     guid,
  63.                 /* repeat */       bool       repeat,
  64.                 /* atTime */       AbsoluteTime ts);
  65. };
  66.  
  67.  
  68. //------------------------------------------------------------------------------
  69. // MBHidInit() - replace the real IOHIDSystem with our imposter.
  70. //------------------------------------------------------------------------------
  71. int
  72. MBHidInit(void)
  73. {
  74.     IOHIDSystem    *p;
  75.     MBHIDHack    *sub;
  76.  
  77.     if(oldVtable != NULL)
  78.     {
  79.         printf("module DoubleCommand already loaded!\n");
  80.         return 1;
  81.     }
  82.     if(myVtable == NULL)
  83.     {
  84.         sub = new MBHIDHack();
  85.         myVtable = *(void **)sub;
  86.         sub->free();
  87.     }
  88.     p = IOHIDSystem::instance();
  89.     oldVtable = *(void **)p;
  90.     *(void **)p = myVtable;
  91.     return 0;
  92. }
  93.  
  94.  
  95. //------------------------------------------------------------------------------
  96. // MBHidExit() - replace our imposter with the real IOHIDSystem.
  97. //------------------------------------------------------------------------------
  98. int
  99. MBHidExit(void)
  100. {
  101.     IOHIDSystem    *p;
  102.  
  103.     if(oldVtable != NULL)
  104.     {
  105.         p = IOHIDSystem::instance();
  106.         if(*(void **)p != myVtable)
  107.         {
  108.             printf("Sorry, cannot unload DoubleCommand!\n");
  109.             return 1;
  110.         }
  111.         *(void **)p = oldVtable;
  112.         oldVtable = NULL;
  113.     }
  114.     return 0;
  115. }
  116.  
  117.  
  118. // key remapping stuff down here.
  119. unsigned char setCommandFlag = 0;
  120. unsigned char setControlFlag = 0;
  121. unsigned char setOptionFlag = 0;
  122. unsigned char setfnFlag = 0;
  123. unsigned char commandHeldDown = 0;
  124. unsigned char optionHeldDown = 0;
  125. unsigned char controlHeldDown = 0;
  126. unsigned char fnHeldDown = 0;
  127. unsigned char inFnMode = 0;
  128. unsigned char unsetCommandFlag = 0;
  129. unsigned char unsetOptionFlag = 0;
  130. unsigned char unsetControlFlag = 0;
  131. unsigned char unsetfnFlag = 0;
  132.  
  133. void MBHIDHack::keyboardEvent(unsigned   eventType,
  134.       /* flags */            unsigned   flags,
  135.       /* keyCode */          unsigned   key,
  136.       /* charCode */         unsigned   charCode,
  137.       /* charSet */          unsigned   charSet,
  138.       /* originalCharCode */ unsigned   origCharCode,
  139.       /* originalCharSet */  unsigned   origCharSet,
  140.       /* keyboardType */     unsigned   keyboardType,
  141.       /* repeat */           bool       repeat,
  142.       /* atTime */           AbsoluteTime ts)
  143. {
  144. #ifdef MB_DEBUG
  145.     printf("caught  hid event type %d flags 0x%x key %d charCode %d charSet %d origCharCode %d origCharSet %d kbdType %d\n", eventType, flags, key, charCode, charSet, origCharCode, origCharSet, keyboardType);
  146. #endif
  147.  
  148. if (dcConfig != 0)
  149. {
  150.     switch (key)
  151.     {
  152.         case ENTER_KEY: // begin enter key
  153.             if (dcConfig & ENTER_TO_COMMAND)
  154.             {
  155.                 if (eventType == KEY_DOWN)
  156.                 {
  157.                     setCommandFlag = 1;
  158.                     key = COMMAND_KEY; // we don't want any enter key stuff to get through
  159.                     eventType = KEY_MODIFY;
  160.                     //charCode = 111;
  161.                     //flags |= COMMAND_FLAG;
  162.                 }
  163.                 else if (eventType == KEY_UP)
  164.                 {
  165.                     setCommandFlag = 0;
  166.                     key = COMMAND_KEY; // we don't want any enter key stuff to get through
  167.                     eventType = KEY_MODIFY;
  168.                 }
  169.             }
  170.             else if (dcConfig & ENTER_TO_CONTROL)
  171.             {
  172.                 if (eventType == KEY_DOWN)
  173.                 {
  174.                     setControlFlag = 1;
  175.                     key = CONTROL_KEY; // we don't want any enter key stuff to get through
  176.                     eventType = KEY_MODIFY;
  177.                 }
  178.                 else if (eventType == KEY_UP)
  179.                 {
  180.                     setControlFlag = 0;
  181.                     key = CONTROL_KEY; // we don't want any enter key stuff to get through
  182.                     eventType = KEY_MODIFY;
  183.                 }
  184.             }
  185.             else if (dcConfig & ENTER_TO_OPTION)
  186.             {
  187.                 if (eventType == KEY_DOWN)
  188.                 {
  189.                     setOptionFlag = 1;
  190.                     key = OPTION_KEY; // we don't want any enter key stuff to get through
  191.                     eventType = KEY_MODIFY;
  192.                 }
  193.                 else if (eventType == KEY_UP)
  194.                 {
  195.                     setOptionFlag = 0;
  196.                     key = OPTION_KEY; // we don't want any enter key stuff to get through
  197.                     eventType = KEY_MODIFY;
  198.                 }
  199.             }
  200.             else if (dcConfig & ENTER_TO_FN)
  201.             {
  202.                 if (eventType == KEY_DOWN)
  203.                 {
  204.                     setfnFlag = 1;
  205.                     key = FN_KEY; // we don't want any enter key stuff to get through
  206.                     eventType = KEY_MODIFY;
  207.                     flags |= FN_FLAG;
  208.                     inFnMode = 1;
  209.                 }
  210.                 else if (eventType == KEY_UP)
  211.                 {
  212.                     setfnFlag = 0;
  213.                     key = FN_KEY; // we don't want any enter key stuff to get through
  214.                     eventType = KEY_MODIFY;
  215.                     inFnMode = 0;
  216.                 }
  217.             }
  218.         break; // end enter key
  219.  
  220.         case COMMAND_KEY: // begin command key
  221.             if (dcConfig & COMMAND_TO_OPTION)
  222.             {
  223.                 if (commandHeldDown) // this event is a key up
  224.                 {
  225.                     commandHeldDown = 0;
  226.                     setOptionFlag = 0;
  227.                     unsetCommandFlag = 0;
  228.                 }
  229.                 else // this event is a key down
  230.                 {
  231.                     commandHeldDown = 1;
  232.                     setOptionFlag = 1;
  233.                     unsetCommandFlag = 1;
  234.                 }
  235.                 key = OPTION_KEY;
  236.             }
  237.             else if (dcConfig & COMMAND_TO_CONTROL)
  238.             {
  239.                 if (commandHeldDown) // this event is a key up
  240.                 {
  241.                     commandHeldDown = 0;
  242.                     setControlFlag = 0;
  243.                     unsetCommandFlag = 0;
  244.                 }
  245.                 else // this event is a key down
  246.                 {
  247.                     commandHeldDown = 1;
  248.                     setControlFlag = 1;
  249.                     unsetCommandFlag = 1;
  250.                 }
  251.                 key = CONTROL_KEY;
  252.             }
  253.             else if (dcConfig & DISABLE_COMMAND_AND_OPTION)
  254.             {
  255.                 if (commandHeldDown) // this event is a key up
  256.                 {
  257.                     commandHeldDown = 0;
  258.                     unsetCommandFlag = 0;
  259.                 }
  260.                 else // this event is a key down
  261.                 {
  262.                     commandHeldDown = 1;
  263.                     unsetCommandFlag = 1;
  264.                 }
  265.             }
  266.         break; // end command key
  267.  
  268.         case OPTION_KEY: // begin option key
  269.             if (dcConfig & OPTION_TO_COMMAND)
  270.             {
  271.                 if (optionHeldDown) // this event is a key up
  272.                 {
  273.                     optionHeldDown = 0;
  274.                     setCommandFlag = 0;
  275.                     unsetOptionFlag = 0;
  276.                 }
  277.                 else // this event is a key down
  278.                 {
  279.                     optionHeldDown = 1;
  280.                     setCommandFlag = 1;
  281.                     unsetOptionFlag = 1;
  282.                 }
  283.                 key = COMMAND_KEY;
  284.             }
  285.             else if (dcConfig & OPTION_TO_FN)
  286.             {
  287.                 if (optionHeldDown) // this event is a key up
  288.                 {
  289.                     optionHeldDown = 0;
  290.                     setfnFlag = 0;
  291.                     unsetOptionFlag = 0;
  292.                 }
  293.                 else // this event is a key down
  294.                 {
  295.                     optionHeldDown = 1;
  296.                     setfnFlag = 1;
  297.                     unsetOptionFlag = 1;
  298.                 }
  299.                 key = FN_KEY;
  300.             }
  301.             else if (dcConfig & DISABLE_COMMAND_AND_OPTION)
  302.             {
  303.                 if (optionHeldDown) // this event is a key up
  304.                 {
  305.                     optionHeldDown = 0;
  306.                     unsetOptionFlag = 0;
  307.                 }
  308.                 else // this event is a key down
  309.                 {
  310.                     optionHeldDown = 1;
  311.                     unsetOptionFlag = 1;
  312.                 }
  313.             }
  314.             else if (dcConfig & SWAP_CONTROL_AND_OPTION) // control <-> option
  315.             {
  316.                 if (optionHeldDown) // this event is a key up
  317.                 {
  318.                     optionHeldDown = 0;
  319.                     setControlFlag = 0;
  320.                     if (!controlHeldDown)
  321.                     {
  322.                         unsetOptionFlag = 0;
  323.                     }
  324.                 }
  325.                 else // this event is a key down
  326.                 {
  327.                     optionHeldDown = 1;
  328.                     setControlFlag = 1;
  329.                     if (!controlHeldDown)
  330.                     {
  331.                         unsetOptionFlag = 1;
  332.                     }
  333.                 }
  334.                 key = CONTROL_KEY;
  335.             }
  336.         break; // end option key
  337.  
  338.         case CONTROL_KEY: // begin control key
  339.             if (dcConfig & CONTROL_TO_COMMAND)
  340.             {
  341.                 if (controlHeldDown) // this event is a key up
  342.                 {
  343.                     controlHeldDown = 0;
  344.                     setCommandFlag = 0;
  345.                     unsetControlFlag = 0;
  346.                 }
  347.                 else // this event is a key down
  348.                 {
  349.                     controlHeldDown = 1;
  350.                     setCommandFlag = 1;
  351.                     unsetControlFlag = 1;
  352.                 }
  353.                 key = COMMAND_KEY;
  354.             }
  355.             else if (dcConfig & SWAP_CONTROL_AND_OPTION) // control <-> option
  356.             {
  357.                 if (controlHeldDown) // this event is a key up
  358.                 {
  359.                     controlHeldDown = 0;
  360.                     setOptionFlag = 0;
  361.                     if (!optionHeldDown)
  362.                     {
  363.                         unsetControlFlag = 0;
  364.                     }
  365.                 }
  366.                 else // this event is a key down
  367.                 {
  368.                     controlHeldDown = 1;
  369.                     setOptionFlag = 1;
  370.                     if (!optionHeldDown)
  371.                     {
  372.                         unsetControlFlag = 1;
  373.                     }
  374.                 }
  375.                 key = OPTION_KEY;
  376.             }
  377.             else if (dcConfig & CONTROL_TO_FN)
  378.             {
  379.                 if (controlHeldDown) // this event is a key up
  380.                 {
  381.                     controlHeldDown = 0;
  382.                     setfnFlag = 0;
  383.                     unsetControlFlag = 0;
  384.                 }
  385.                 else // this event is a key down
  386.                 {
  387.                     controlHeldDown = 1;
  388.                     setfnFlag = 1;
  389.                     unsetControlFlag = 1;
  390.                 }
  391.                 key = FN_KEY;
  392.             }
  393.         break; // end control key
  394.  
  395.         case FN_KEY: // begin fn key
  396.             if (dcConfig & FN_TO_CONTROL)
  397.             {
  398.                 if (fnHeldDown) // this event is a key up
  399.                 {
  400.                     fnHeldDown = 0;
  401.                     setControlFlag = 0;
  402.                     unsetfnFlag = 0;
  403.                 }
  404.                 else // this event is a key down
  405.                 {
  406.                     fnHeldDown = 1;
  407.                     setControlFlag = 1;
  408.                     unsetfnFlag = 1;
  409.                 }
  410.                 key = CONTROL_KEY;
  411.             }
  412.         break; // end fn key
  413.  
  414.         case DELETE_KEY: // begin delete key
  415.             // Make Shift + Delete send a Forward Delete key
  416.             // This doesn't conflict with anything I know of and is handy
  417.             if (dcConfig & SHIFT_DELETE_TO_FORWARD_DELETE)
  418.             {
  419.                 //if (eventType == KEY_DOWN || eventType == KEY_UP)
  420.                 //{
  421.                     if (flags == SHIFT_FLAG) // with _only_ shift held as well
  422.                     {
  423.                         key = FORWARD_DELETE;
  424.                         //flags ^= 0x20000;
  425.                         flags = FN_FLAG;
  426.                         charCode = 45;
  427.                         charSet = 254;
  428.                         origCharCode = 45;
  429.                         origCharSet = 254;
  430.                     }
  431.                 //}
  432.             }
  433.         break; // end delete key
  434.  
  435.         // begin supplied by Giel Scharff <mgsch@mac.com>
  436.         case NUMPAD_DOT: // begin numpad dot
  437.             if (dcConfig & REVERSE_NUMPAD_DOT_AND_SHIFT_NUMPAD_DOT)
  438.             {
  439.                 if (eventType == KEY_DOWN && (flags == 0x200000)) // key down without shift held as well
  440.                 {
  441.                     //key = 65;
  442.                     flags = 0x220000;
  443.                 }
  444.                 else if (eventType == KEY_DOWN && (flags == 0x220000)) // key down with shift held as well
  445.                 {
  446.                     //key = 65;
  447.                     flags = 0x200000;
  448.                 }
  449.             }
  450.         break; // end numpad dot
  451.         // end supplied by Giel Scharff <mgsch@mac.com>
  452.  
  453.         case CAPSLOCK_KEY: // begin capslock key
  454.             if(dcConfig & CAPSLOCK_TO_CONTROL)
  455.             {
  456.                 // has the capslock key has been pressed?
  457.                 if (eventType == KEY_MODIFY)
  458.                 {
  459.                     key = CONTROL_KEY;
  460.                     // flavor 6 is the kind the titanium comes with
  461.                     // flavor 4 seems to be the type for USB keyboards
  462.                     // keyboardType 195 seems to be the TiBooks internal keyboard
  463.                     // (cachedFlavor will not be set correctly until keyboardSpecialEvent
  464.                     // is called)
  465.                     //if (cachedFlavor == 6 || keyboardType == INTERNAL_KYBD)
  466.                     //{
  467.                         // make it look like the control key has been pressed instead
  468.                         if (flags & CAPSLOCK_FLAG)
  469.                         {
  470.                             // capslock on
  471.                             //addFlags |= CTRL_FLAG;
  472.                             setControlFlag = 1;
  473.                         }
  474.                         else
  475.                         {
  476.                             setControlFlag = 0;
  477.                         }
  478.                         //else if (addFlags & CTRL_FLAG)
  479.                         //{
  480.                             /* capslock off (not the same as releasing capslock, mind you) */
  481.                         //    addFlags ^= CTRL_FLAG;
  482.                         //}
  483.                     //}
  484.                 }
  485.             }
  486.         break; // end capslock key
  487.     } // end switch (key)
  488.  
  489.     // begin supplied by Giel Scharff <mgsch@mac.com>
  490.     if (inFnMode)
  491.     {   //up -> PgUp
  492.         if ((key == 126) && (flags == 0x200000) && (charCode == 173) && (charSet == 1) &&
  493.       (origCharCode == 173) && (origCharSet == 1))
  494.         {
  495.             key = 116; flags = 0x800000; charCode =  48; charSet = 254; origCharCode =  48;  origCharSet = 254;
  496.         }
  497.         //down -> PgDown
  498.         else if ((key == 125) && (flags == 0x200000) && (charCode == 175) && (charSet == 1) &&
  499.            (origCharCode == 175) && (origCharSet == 1))
  500.         {
  501.             key = 121; flags = 0x800000; charCode =  49; charSet = 254; origCharCode =  49;  origCharSet = 254;
  502.         }
  503.         //left -> Home
  504.         else if ((key == 123) && (flags == 0x200000) && (charCode == 172) && (charSet == 1) &&
  505.            (origCharCode == 172) && (origCharSet == 1))
  506.         {
  507.             key = 115; flags = 0x800000; charCode =  46; charSet = 254; origCharCode =  46;  origCharSet = 254;
  508.         }
  509.         //right -> End
  510.         else if ((key == 124) && (flags == 0x200000) && (charCode == 174) && (charSet == 1) &&
  511.            (origCharCode == 174) && (origCharSet == 1))
  512.         {
  513.             key = 119; flags = 0x800000; charCode =  47; charSet = 254; origCharCode =  46;  origCharSet = 254;
  514.         }
  515.     }
  516.     // end supplied by Giel Scharff <mgsch@mac.com>
  517.  
  518.     // wipe out capslock entirely
  519.     //if (flags & CAPS_FLAG)
  520.     //{
  521.     //    flags ^= CAPS_FLAG;
  522.     //}
  523.  
  524.     if (unsetCommandFlag)
  525.     {
  526.         flags ^= COMMAND_FLAG;
  527.         //flags ^= 0x100000;
  528.     }
  529.     if (unsetOptionFlag)
  530.     {
  531.         flags ^= OPTION_FLAG;
  532.     }
  533.     if (unsetControlFlag)
  534.     {
  535.         flags ^= CONTROL_FLAG;
  536.     }
  537.     if (unsetfnFlag)
  538.     {
  539.         flags ^= FN_FLAG;
  540.     }
  541.     if (setCommandFlag)
  542.     {
  543.         flags |= COMMAND_FLAG;
  544.     }
  545.     if (setControlFlag)
  546.     {
  547.         flags |= CONTROL_FLAG;
  548.     }
  549.     if (setOptionFlag)
  550.     {
  551.         flags |= OPTION_FLAG;
  552.     }
  553.     if (setfnFlag)
  554.     {
  555.         flags |= FN_FLAG;
  556.     }
  557. #ifdef MB_DEBUG
  558.     printf("sending hid event type %d flags 0x%x key %d charCode %d charSet %d origCharCode %d origCharSet %d kbdType %d\n", eventType, flags, key, charCode, charSet, origCharCode, origCharSet, keyboardType);
  559. #endif
  560. } // end if dcConfig != 0
  561.     IOHIDSystem::keyboardEvent(eventType, flags, key, charCode, charSet, origCharCode, origCharSet, keyboardType, repeat, ts);
  562. }
  563.  
  564. void MBHIDHack::keyboardSpecialEvent(   unsigned   eventType,
  565.                        /* flags */        unsigned   flags,
  566.                        /* keyCode  */     unsigned   key,
  567.                        /* specialty */    unsigned   flavor,
  568.                        /* guid */         UInt64     guid,
  569.                        /* repeat */       bool       repeat,
  570.                        /* atTime */       AbsoluteTime ts)
  571. {
  572. #ifdef MB_DEBUG
  573.     printf("special event type %d flags 0x%x key %d flavor %d\n", eventType, flags, key, flavor);
  574. #endif
  575.     IOHIDSystem::keyboardSpecialEvent(eventType, flags, key, flavor, guid, repeat, ts);
  576. }
  577.